#ifndef MAIN_H
#define MAIN_H

#include <joystick.h>
#include <nes.h>
#include <stdint.h>
#include "neslib.h"
#include "chrs.h"

typedef uint32_t u32;
typedef uint16_t u16;
typedef uint8_t u8;

typedef int32_t s32;
typedef int16_t s16;
typedef int8_t s8;

void bankswitch(const u8 bank, const u8 file);

enum {
	G_DEMO,
	G_SINGLE_A,
	G_SINGLE_B,
	G_TWO_A,
	G_TWO_B,
};

enum {
	C_DENIRO,
	C_PRISONER,
	C_ENT1,
	C_ENT2,
	C_WALKEN
};

enum {
	S_SETUP_LOAD,
	S_SHOW_BULLET,
	S_LOAD,
	S_LOADED,
	S_SETUP_SPIN,
	S_SPIN,
	S_SPINWAIT,
	S_SHOOT,
	S_RESULTS,

	S_SLAPPING
};

enum {
	SFX_INSERT_ROUND = 0,
	SFX_CHAMBER_CLOSE,
	SFX_SPINNING_CHAMBER,
	SFX_REVOLVER_SPIN,
	SFX_PULL_TRIGGER,
	SFX_SHOT,
	SFX_CROWD_SHORT,
	SFX_CROWD_MEDIUM,
	SFX_CROWD_LONG,
	SFX_SLAP1,
	SFX_SLAP2,
	SFX_PENALTY,
	SFX_LIGHTGUN // unused
};

enum {
	MUSIC_TITLE,
	MUSIC_GAME_START, // press start at title screen
	MUSIC_FIRST_ROUND,
	MUSIC_ROUND_END,
	MUSIC_NEXT_ROUND, // all rounds but the first
	MUSIC_GAMEOVER, // after shooting yourself
	MUSIC_GAMEOVER2, // after three strikes
	MUSIC_FIRST_ROUND_BETA // unused
};

// Globals
extern u8 gamemode;
#pragma zpsym("gamemode")
extern u8 zapper;
#pragma zpsym("zapper")

extern u8 bgbuf[128];
#pragma zpsym("bgbuf")
extern u8 scorebuf[7];
#pragma zpsym("scorebuf")

extern u16 addr;
#pragma zpsym("addr")
extern u8 oam_off;
#pragma zpsym("oam_off")
extern u8 zappershot, zapperdark, zappertmp;
#pragma zpsym("zappershot")
#pragma zpsym("zapperdark")
#pragma zpsym("zappertmp")

extern u8 sfxctr;
extern u16 musicctr, musiclimit;
#pragma zpsym("sfxctr")
#pragma zpsym("musicctr")
#pragma zpsym("musiclimit")

// game.c ZP vars
extern u8 x, y, i, ctrl, ctrl2, spintime, aiming, spinchange, progress;
#pragma zpsym("x")
#pragma zpsym("y")
#pragma zpsym("i")
#pragma zpsym("ctrl")
#pragma zpsym("ctrl2")
#pragma zpsym("spintime")
#pragma zpsym("aiming")
#pragma zpsym("spinchange")
#pragma zpsym("progress")
extern u8 spinprogress, spinframe, prevctrl, prevctrl2, bulletstate[3], five, otherchar;
#pragma zpsym("spinprogress")
#pragma zpsym("spinframe")
#pragma zpsym("prevctrl")
#pragma zpsym("prevctrl2")
#pragma zpsym("bulletstate")
#pragma zpsym("five")
#pragma zpsym("otherchar")
extern u8 cocked, died, face1, face2, whichdeath, yelled[2], totalstrikes[2];
#pragma zpsym("cocked")
#pragma zpsym("died")
#pragma zpsym("face1")
#pragma zpsym("face2")
#pragma zpsym("whichdeath")
#pragma zpsym("yelled")
#pragma zpsym("totalstrikes")
extern u16 strikecnt, strikelimit;
#pragma zpsym("strikecnt")
#pragma zpsym("strikelimit")
extern u8 turn, shoottimer;
#pragma zpsym("turn")
#pragma zpsym("shoottimer")
extern u8 aiwait, aihesitate;
#pragma zpsym("aiwait")
#pragma zpsym("aihesitate")
extern u8 eggshot, eggfirst;
#pragma zpsym("eggshot")
#pragma zpsym("eggfirst")

// Saved vars
extern u16 topscore[4], checksum;

// title.c
void title(void);

// game.c
void game(void);

// main.c
void resetscores(void);
void shotscreen(void);

// helpers.c
void fadein(void);
void fadeout(void);
void pal_nt(u8 x, u8 y, const u8 col);
void str(const char *msg);

// strconv.c
void fmtscore(const u16 num);
void utoa4(char * const buf, u16 num);

// curve.c
extern const u8 curve[256];

// data.c
extern const u8 numdeath[5][2];
extern const u8 deathpos[5][2];
extern const u8 walkenpal[3];
extern const u8 deniropal[3];
extern const u8 prisonerpal[3];
extern const u8 ent1pal[3];
extern const u8 ent2pal[3];
extern const u8 bulletpos[2][12];

// metasprites
extern const u8 blast1_metasprite[];
extern const u8 blast2_metasprite[];
extern const u8 blast1_metasprite_flip[];
extern const u8 blast2_metasprite_flip[];
extern const u8 bullet_metasprite[];
extern const u8 smallchamber_metasprite[];
extern const u8 chamber1_metasprite[];
extern const u8 chamber2_metasprite[];
extern const u8 hammer1_metasprite[];
extern const u8 hammer2_metasprite[];
extern const u8 hammer3_metasprite[];
extern const u8 hammer4_metasprite[];
extern const u8 hammer5_metasprite[];
extern const u8 hammer1_metasprite_flip[];
extern const u8 hammer2_metasprite_flip[];
extern const u8 hammer3_metasprite_flip[];
extern const u8 hammer4_metasprite_flip[];
extern const u8 hammer5_metasprite_flip[];
extern const u8 hand1_metasprite[];
extern const u8 hand2_metasprite[];
extern const u8 hand3_metasprite[];
extern const u8 hand4_metasprite[];
extern const u8 hand5_metasprite[];
extern const u8 hand1_metasprite_flip[];
extern const u8 hand2_metasprite_flip[];
extern const u8 hand3_metasprite_flip[];
extern const u8 hand4_metasprite_flip[];
extern const u8 hand5_metasprite_flip[];
extern const u8 hand_cocking_metasprite[];
extern const u8 hand_cocking_metasprite_flip[];
extern const u8 revolver_small_chamber_metasprite[];
extern const u8 revolver_small_metasprite[];
extern const u8 revolver_small_chamber_metasprite_flip[];
extern const u8 revolver_small_metasprite_flip[];
extern const u8 round_metasprite[];
extern const u8 slaphand_metasprite[];
extern const u8 slaphand_metasprite_flip[];
extern const u8 strike_metasprite[];

extern const u8 * const hand_array[5];
extern const u8 * const hammer_array[5];

extern const u8 * const hand_array_flip[5];
extern const u8 * const hammer_array_flip[5];

#endif
